﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;

public class TileObject : MonoBehaviour
{
    public int tileX;

    public int tileY;

    public bool isCollider = false;

    private TileContainer m_RootContainer;
    
    private TileContainer _rootContainer
    {
        get
        {
            if (m_RootContainer == null)
            {
                m_RootContainer = transform.parent.GetComponent<TileContainer>();
            }

            return m_RootContainer;
        }
        set
        {
            m_RootContainer = value;
        }
    }

    public PlayerBuilding playerBuildingTemplet;

    public BaseContent content;

    public void CreateTileObject(TileContainer root, int x, int y)
    {
        this._rootContainer = root;
        this.tileX = x;
        this.tileY = y;
        this.transform.localPosition = root.tileOffset + new Vector2(root.tileSize * tileX, root.tileSize * tileY);
    }

    public void Init()
    {
        this.transform.localPosition = _rootContainer.tileOffset + new Vector2(_rootContainer.tileSize * tileX, _rootContainer.tileSize * tileY);
        this.content = GetComponentInChildren<BaseContent>();
        if (this.content != null)
        {
            this.content.rootTile = this;
        }

        if (playerBuildingTemplet == null)
        {
            playerBuildingTemplet = GameManager.Instance.playerBuildingTemplet;
        }
    }
    
#if UNITY_EDITOR
    void OnDrawGizmos()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(transform.position, Vector3.one * _rootContainer.tileSize);
    }
#endif

    /// <summary>
    /// Get Manhattan Distance to another Tile
    /// </summary>
    /// <param name="otherTile"></param>
    /// <returns></returns>
    public int DistanceTo(TileObject otherTile)
    {
        return Mathf.Abs(otherTile.tileX - this.tileX) + Mathf.Abs(otherTile.tileY - this.tileY);
    }

    public bool CanArrive()
    {
        return !isCollider && (content == null || content.CanArrive());
    }

    private bool TryMove(int x, int y, out TileObject next)
    {
        next = this;
        if (x < 0 || y < 0 || x >= _rootContainer.tiles.GetLength(0) || y >= _rootContainer.tiles.GetLength(1))
        {
            return false;
        }

        var nextTile = _rootContainer.GetTileObject(x, y);

        if (!nextTile.CanArrive())
        {
            return false;
        }

        next = nextTile;
        return true;
    }

    public bool TryLeft(out TileObject next)
    {
        int nextPositionX = tileX - 1;
        int nextPositionY = tileY;
        if (!TryMove(nextPositionX, nextPositionY, out next))
        {
            return false;
        }
        return true;
    }
    
    public bool TryRight(out TileObject next)
    {
        int nextPositionX = tileX + 1;
        int nextPositionY = tileY;
        if (!TryMove(nextPositionX, nextPositionY, out next))
        {
            return false;
        }
        return true;
    }
    
    public bool TryUp(out TileObject next)
    {
        int nextPositionX = tileX;
        int nextPositionY = tileY + 1;
        if (!TryMove(nextPositionX, nextPositionY, out next))
        {
            return false;
        }
        return true;
    }
    
    public bool TryDown(out TileObject next)
    {
        int nextPositionX = tileX;
        int nextPositionY = tileY - 1;
        if (!TryMove(nextPositionX, nextPositionY, out next))
        {
            return false;
        }
        return true;
    }

    public bool TryBuild()
    {
        if (content == null)
        {
            var buildingObj = GameObject.Instantiate(playerBuildingTemplet.gameObject, transform);
            buildingObj.SetActive(true);
            content = buildingObj.GetComponent<PlayerBuilding>();
            return true;
        }

        return false;
    }
}
